use std::marker::PhantomData;

use crate::message::EventResult;
use crate::sequence::ViewMarker;
use crate::view::Cx;
use crate::widget::{ChangeFlags, Pod};
use crate::{id::Id, view::View};

pub struct Scroll<T, V: View<T>> {
    children: V,
    _phantom_data: PhantomData<T>,
}

impl<T, V: View<T>> ViewMarker for Scroll<T, V> {}

impl<T, V: View<T>> Scroll<T, V> {
    pub fn new(children: V) -> Self {
        Self {
            children,
            _phantom_data: Default::default(),
        }
    }
}

impl<T, V: View<T>> View<T> for Scroll<T, V>
where
    V::Element: 'static,
{
    type State = (Id, V::State);

    type Element = crate::widget::Scroll;

    fn build(&self, cx: &mut Cx) -> (Id, Self::State, Self::Element) {
        let (scroll_id, (id, state, element)) = cx.with_new_id(|cx| self.children.build(cx));
        let scroll = crate::widget::Scroll::new(Pod::new(element));
        (scroll_id, (id, state), scroll)
    }

    fn rebuild(
        &self,
        prev: &Self,
        cx: &mut Cx,
        id: &mut Id,
        state: &mut Self::State,
        element: &mut Self::Element,
    ) -> ChangeFlags {
        let pod = element.children_mut();
        let el = pod.widget.as_any_mut().downcast_mut().unwrap();
        self.children
            .rebuild(&prev.children, cx, id, &mut state.1, el)
    }

    fn message(
        &self,
        id_path: &[Id],
        state: &mut Self::State,
        event: Box<dyn std::any::Any>,
        app_state: &mut T,
    ) -> EventResult<()> {
        if let Some((head, body)) = id_path.split_first() {
            if head == &state.0 {
                return self.children.message(body, &mut state.1, event, app_state);
            }
        }
        EventResult::Stale(event)
    }
}
